package cn.demoncat.util.oss.qiniu;

import cn.demoncat.util.exception.BizRuntimeException;
import cn.demoncat.util.exception.ParamRuntimeException;
import cn.demoncat.util.io.FileNameUtil;
import cn.demoncat.util.lang.ParamEmptyUtil;
import cn.demoncat.util.lang.constant.StringConstant;
import cn.demoncat.util.oss.qiniu.config.QiniuOssProperties;
import com.qiniu.common.QiniuException;
import com.qiniu.storage.*;
import com.qiniu.storage.model.FileInfo;
import com.qiniu.util.Auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/**
 * 七牛云OSS
 *
 * @author 延晓磊
 * @since 2022年07月11日
 */
@Component
public class QiniuOssUtil {

    private final QiniuOssProperties properties;
    private final Configuration configuration;
    private final Auth auth;

    /**
     * 初始化
     *
     * @param qiniuOssProperties
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    @Autowired
    public QiniuOssUtil(QiniuOssProperties qiniuOssProperties){
        this.properties = qiniuOssProperties;
        // 指定区域
        Region region;
        switch (qiniuOssProperties.getRegion()) {
            case 0:
                region = Region.huadong();
                break;
            case 1:
                region = Region.huabei();
                break;
            case 2:
                region = Region.huanan();
                break;
            default:
               throw new ParamRuntimeException("配置文件oss.qiniu.region错误");
        }
        // 校验参数
        ParamEmptyUtil.checkBlank(properties.getAk(), properties.getSk(), properties.getBucket(), properties.getDomain());
        // 创建配置
        this.configuration = new Configuration(region);
        // 创建认证
        this.auth = Auth.create(qiniuOssProperties.getAk(), qiniuOssProperties.getSk());
    }

    /**
     * 上传文件
     *
     * @param file  文件路径
     * @param name  文件名称（唯一标识，重复时报错）
     * @return
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String upload(String file, String name){
        try {
            new UploadManager(configuration).put(file, name, auth.uploadToken(properties.getBucket()));
        } catch (QiniuException ex) {
            throw new BizRuntimeException("上传文件失败：" + ex.error(), ex);
        }
        return name;
    }

    /**
     * 上传文件
     *
     * @param file  文件
     * @param name  文件名称（唯一标识，重复时报错）
     * @return
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String upload(File file, String name){
        try {
            new UploadManager(configuration).put(file, name, auth.uploadToken(properties.getBucket()));
        } catch (QiniuException ex) {
            throw new BizRuntimeException("上传文件失败：" + ex.error(), ex);
        }
        return name;
    }

    /**
     * 上传文件
     *
     * @param file  文件
     * @param name  文件名称（唯一标识，重复时报错）
     * @return
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String upload(byte[] file, String name){
        try {
            new UploadManager(configuration).put(file, name, auth.uploadToken(properties.getBucket()));
        } catch (QiniuException ex) {
            throw new BizRuntimeException("上传文件失败：" + ex.error(), ex);
        }
        return name;
    }

    /**
     * 上传文件
     *
     * @param file  文件
     * @param name  文件名称（唯一标识，重复时报错）
     * @return
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String upload(InputStream file, String name){
        try {
            new UploadManager(configuration).put(file, name, auth.uploadToken(properties.getBucket()), null, null);
        } catch (QiniuException ex) {
            throw new BizRuntimeException("上传文件失败：" + ex.error(), ex);
        }
        return name;
    }

    /**
     * 上传文件
     *
     * @param file  文件
     * @return
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String upload(MultipartFile file){
        try {
            return upload(file.getInputStream(), FileNameUtil.getRandomName(file.getOriginalFilename())) + StringConstant.HASH + file.getOriginalFilename();
        } catch (IOException ex) {
            throw new BizRuntimeException("上传文件失败：读取文件失败", ex);
        }
    }

    /**
     * 删除文件
     *
     * @param name  文件名
     * @return 删除 true, 不存在 false
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public boolean delete(String name){
        BucketManager manager = new BucketManager(auth, configuration);
        try {
            manager.delete(properties.getBucket(), name);
            return true;
        } catch (QiniuException ex) {
            if (ex.code() == 612) {
                // 文件不存在
                return false;
            }
            throw new BizRuntimeException("删除文件失败：" + ex.error(), ex);
        }
    }

    /**
     * 查看文件信息
     *
     * @param name
     * @return 存在 {fsize,putTime}，不存在 null
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public FileInfo info(String name){
        BucketManager manager = new BucketManager(auth, configuration);
        try {
            return manager.stat(properties.getBucket(), name);
        } catch (QiniuException ex) {
            if (ex.code() == 612) {
                // 文件不存在
                return null;
            }
            throw new BizRuntimeException("查看文件失败：" + ex.error(), ex);
        }
    }

    /**
     * 获取文件地址
     *
     * @param name
     * @return 文件地址：http://url/name
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String url(String name){
        try {
           return new DownloadUrl(properties.getDomain(), false, name).buildURL();
        } catch (QiniuException ex) {
            throw new BizRuntimeException("下载文件失败：" + ex.error(), ex);
        }
    }

    /**
     * 获取文件地址L
     *
     * @param name
     * @return 文件地址：https://url/name
     *
     * @author 延晓磊
     * @since 2022年07月11日
     */
    public String urls(String name){
        try {
            return new DownloadUrl(properties.getDomain(), true, name).buildURL();
        } catch (QiniuException ex) {
            throw new BizRuntimeException("下载文件失败：" + ex.error(), ex);
        }
    }
}
